<?php

namespace traits\controller;

use think\facade\Db;

trait ListTraits
{

  /**
   * 获取查询条件
   * @param array $withFields
   * @param array $withData
   * @param array $query
   * @return array
   */
  protected function getQuery($withFields = [], $withData = [], $query = [])
  {
    request()->filter(['strip_tags']);
    $pageSize   = request()->param('pageSize/d', 20); //每页多少条
    $pageNumber = request()->param('pageNumber/d', 1); //当前页
    $sortName   = request()->param('sortName'); //排序字段
    $sortOrder  = request()->param('sortOrder', 'desc'); //升序降序
    //排序
    if (isset($withData['order'])) {
      $order = $withData['order'];
      unset($withData['order']);
    } else {
      $order = !empty($sortName) ? "{$sortName} {$sortOrder}" : ''; //排序
    }
    //格式化检索
    $filter     = request()->param('filter', '', null); //搜索字段值 json
    $withFields = array_merge(['filter'], $withFields);
    if (isset($withData['filter'])) {
      $filter = array_merge($filter, $withData['filter']);
      unset($withData['filter']);
    }
    $withData = array_merge(['filter' => $filter], $withData);
    //字段、字段值检索
    $searchField = request()->param('search_field/s');
    $searchValue = request()->param('search_value/s');
    $searchField = preg_match("/^[a-z0-9_.|&]+$/", $searchField) ? $searchField : '';
    $searchValue = addslashes($searchValue); //转义特殊字符
    if (!empty($searchField) && !empty($searchValue)) {
      $query[] = [$searchField, 'like', '%' . $searchValue . '%'];
    }
    return [
        'withFields' => $withFields,
        'withData' => $withData,
        'query' => $query,
        'order' => $order,
        'pageNumber' => $pageNumber,
        'pageSize' => $pageSize,
    ];
  }

  /**
   * 分页数据
   * @param string $name 模型路径用.隔开
   * @param array $withFields 额外搜索器字段
   * @param array $withData 额外搜索器数据
   * @param array $query 额外查询条件
   * @return array
   */
  protected function getPage($name = null, $withFields = [], $withData = [], $query = [])
  {
    $res   = $this->getQuery($withFields, $withData, $query);
    $model = empty($name) ? $this->model : D($name);
    try {
      $data          = ['total' => 0, 'rows' => []];
      $data['total'] = $model->withSearch($res['withFields'], $res['withData'])->where($query)->count();
      if ($data['total'] > 0) {
        $list         = $model->withSearch($res['withFields'], $res['withData'])
            ->where($res['query'])
            ->order($res['order'])
            ->page((int)$res['pageNumber'], (int)$res['pageSize'])
            ->select();
        $data['rows'] = $list->isEmpty() ? [] : $list;
      }
    } catch (\Exception $e) {
      $data = ['total' => 0, 'rows' => [], 'err_msg' => $e->getMessage()];
    }
    return $data;
  }

  /**
   * 列表数据
   * @param $name
   * @param array $withFields 额外搜索器字段
   * @param array $withData 额外搜索器数据
   * @param array $query 额外查询条件
   * @return array
   */
  protected function getList($name = null, $withFields = [], $withData = [], $query = [])
  {
    $res   = $this->getQuery($withFields, $withData, $query);
    $model = empty($name) ? $this->model : D($name);
    try {
      $list = $model->withSearch($res['withFields'], $res['withData'])
          ->where($res['query'])
          ->order($res['order'])
          ->select();
    } catch (\Exception $e) {
      $list = [];
    }
    return $list->isEmpty() ? [] : $list;
  }

  /**
   * 组装selectPage查询条件
   * @return array
   */
  protected function getSelectPageQuery()
  {
    request()->filter(['strip_tags']);
    $pageNumber = request()->param('pageNumber/d'); //当前页数
    $pageSize   = request()->param('pageSize/d', 10); //每页记录数
    //处理排序
    $orderBy = (array)request()->request("orderBy/a");
    $order   = [];
    foreach ($orderBy as $k => $v) {
      $order[$v[0]] = $v[1];
    }
    //处理默认选中
    $searchTable = request()->param('searchTable'); //查询字段前缀
    $searchKey   = request()->param('searchKey'); //查询初始化数据
    $searchValue = request()->param('searchValue'); //查询初始化数据
    $map         = [];
    if (!empty($searchKey) && !empty($searchValue)) {
      if ($searchTable != 'tbl') $searchKey = $searchTable . '.' . $searchKey;
      $map[] = [$searchKey, 'in', $searchValue];
    }
    //字段搜索
    $word        = (array)request()->param("q_word/a"); //搜索关键词,客户端输入以空格分开,这里接收为数组
    $andOr       = request()->param("andOr", "and", "strtoupper"); //搜索条件
    $logic       = $andOr == 'AND' ? '&' : '|';
    $searchField = request()->request("searchField"); //搜索字段逗号隔开
    if (!empty($searchField) && !empty($word)) {
      foreach ($word as $k => $v) {
        if (!empty($v)) {
          $map[] = [str_replace(',', $logic, $searchField), "like", "%{$v}%"];
        }
      }
    }
    //自定义搜索
    $query = request()->param('query');
    if (!empty($query)) {
      $map[] = ['', 'EXP', Db::raw($query)];
    }
    return [
        'pageNumber' => (int)$pageNumber,
        'pageSize' => (int)$pageSize,
        'order' => $order,
        'map' => $map
    ];
  }

  /**
   * 获取对应模型selectPage数据
   * @param $name
   * @return \think\response\Json
   */
  protected function getSelectPage($name = null)
  {
    $params = $this->getSelectPageQuery();
    $model  = empty($name) ? $this->model : D($name);
    $total  = $model->where($params['map'])->count();
    $list   = [];
    if ($total > 0) {
      $fields = request()->param('fields', true);
      $list   = $model->field($fields)->where($params['map'])
          ->order($params['order'])
          ->page($params['pageNumber'], $params['pageSize'])
          ->select()->toArray();
    }
    $data['totalRow'] = $total;
    $data['list']     = $list;
    return json($data);
  }

  /**
   * 验证数据
   * @access protected
   * @param array $data 数据
   * @param string|array $validate 验证器名或者验证规则数组
   * @param array $message 提示信息
   * @param bool $batch 是否批量验证
   * @param bool $failException 是否排除异常
   * @return array|string|true
   */
  protected function validate(array $data, $validate, array $message = [], bool $batch = false, bool $failException = true)
  {
    return validate($validate, $message, $batch, $failException)->check($data);
  }

}